/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pl.edu.amu.wmi.kino.visualjavafx.javafxcodeparsers.tools;

import java.util.ArrayList;

/**
 * I've created you a method that cam divide document into instructions
 * @author psychollek
 */
public class InstructionDivider {
    
    int i = 0;

    /**
     * this method divides you a proper JavaFx (or java !) document into
     * instructions, you can have two three of them :
     * 1. simple instruction like:
     *      SomeObject.someMethod(SomeArgument);
     *    which is represented as string:
     *      "SomeObject.someMethod(SomeArgument)"
     * 2. keword with block of instructions like:
     *      class SomeClass{
     *                instruction1;
     *                instruction2;
     *                ....
     *                instructionN;
     *            }
     *    which is represented as  x = Object[2]
     *      with x[0] containing String:
     *         "class SomeClass"
     *      and x[1] containing array of instructions
     *    in case the block would be simply standing alone:
     *      {
     *          instruction1;
     *          instruction2;
     *          ....
     *          instructionN;
     *      }
     *     the x[0] would consist of empty string.
     *
     * other cases :
     * a) the [something] is passed just as it would be a string in " " - if you
     *    have a need to parse the content of it - simply put it through this
     *    method - that is for now at least.
     * b) same with ( ) pairs - for example :
     *    for(x;y;z){a;b;c;} will get you {"for(x;y;z)",{"a","b",c"}}
     *    as this is in fact one instruction !
     *
     * @param in the String representing the document to be parsed
     * @return array of objects - instructions;
     */

    public synchronized Object[] divide(String in){

        int end = in.length();
        ArrayList<Object> arr = new ArrayList<Object>();
        String tmp = new String();


        while (i < end && in.charAt(i) != '}'){

            if (in.regionMatches(i, "//", 0, 2)){                               // comments are thrown out
                while ( i!=end && in.charAt(i) != '\n' ){
                    i++;
                }
            }else if(in.regionMatches(i, "/*", 0, 2)){                          //multiline comments as well
                while ((i+1)!=end && !(in.regionMatches(i, "*/", 0, 2)) ){
                    i++;
                }
                i++;
            }else if(in.charAt(i) == ';'){                                      // method divider ! ;]
                arr.add(tmp.trim());
                tmp = new String();
                i++;                                                            // the ';' char
            }else if(in.charAt(i) == '"'){                                      // strings are chached
                tmp = tmp + in.charAt(i);
                i++;
                while ( i!=end && in.charAt(i) != '"' ){
                    
                    tmp = tmp = tmp + in.charAt(i);
                    i++;
                    
                }
                tmp = tmp + in.charAt(i);
                i++;
                
            }else if(in.charAt(i) == '\''){                                     // chars/strings are cathed
                tmp = tmp + in.charAt(i);
                i++;
                while ( i!=end && in.charAt(i) != '\'' ){
                    tmp = tmp = tmp + in.charAt(i);
                    i++;
                }
                tmp = tmp + in.charAt(i);
                i++;
            }else if(in.charAt(i) == '('){                                      // content in () pairs is catched
                tmp = tmp + in.charAt(i);
                i++;
                int j = 0;
                while ( i!=end && (in.charAt(i) != ')' || j>0 ) ){
                    if (in.charAt(i) == '('){
                        j++;
                    }else if(in.charAt(i) == ')'){
                        j--;
                    }
                    tmp = tmp + in.charAt(i);
                    i++;
                }
                tmp = tmp + in.charAt(i);
                i++;
            }else if(in.charAt(i) == '['){                                      // content in [] pairs is catched
                tmp = tmp + in.charAt(i);
                i++;
                int j = 0;
                while ( i!=end && (in.charAt(i) != ']'|| j>0) ){
                    if (in.charAt(i) == '['){
                        j++;
                    }else if(in.charAt(i) == ']'){
                        j--;
                    }
                    tmp = tmp = tmp + in.charAt(i);
                    i++;
                }
                tmp = tmp + in.charAt(i);
                i++;
            }else if(in.charAt(i) == '{'){                                      // blocks of code are catched and converted
                i++;                                                            // the '{' char
                Object[] x = new Object[2];
                x[0] = tmp.trim();
                tmp = new String();
                x[1] = divide(in);
                arr.add(x);
                i++;                                                            // the '}' char
            }else if(                                                           // whitespaces trimmer (only spaces or '\n' though)
                    (in.charAt(i)=='\r')
                    ||
                     (
                      (
                       (in.charAt(i)==' ')
                       ||(in.charAt(i)=='\n')
                      )
                      && i==0
                     )
                     || (
                         ((in.charAt(i) == ' ')
                          || (in.charAt(i) == '\n')
                         )
                         && (
                             (in.charAt(i-1) == ' ')
                             || (in.charAt(i-1)=='\n')
                                || (in.charAt(i-1)==';')                        //added to fix ;\n problem
                            )
                        )
                    ){
                i++;
            }else if(in.charAt(i)=='\n'){                                       // if encounter '\n' that is int a whitespace - convert it to ' '
                tmp = tmp + in.charAt(i);
                i++;
            }else{                                                              // and finally actual methods are added
                tmp = tmp + in.charAt(i);
                i++;
            }
        }
        arr.add(tmp.trim());                                                    // in case there would be unterminated instruction in a block

        return arr.toArray();
    }
}